<template><div><h2 id="说说spring的事务隔离级别" tabindex="-1"><a class="header-anchor" href="#说说spring的事务隔离级别"><span>说说Spring的事务隔离级别？</span></a></h2>
<p>Spring的事务隔离级别是指在并发环境下，事物之间相互隔离的程度。
以下是常见的事务隔离级别：</p>
<ol>
<li><strong>DEFAULT（默认）：</strong> 使用数据库默认的事务隔离级别。通常为数据库的默认隔离级别，如Oracle为READ COMMITTED，MySQL为REPEATABLE READ。</li>
<li><strong>READ_UNCOMMITTED（读未提交）：</strong></li>
<li><strong>READ_COMMITTED（读已提交）：</strong></li>
<li><strong>REPEATABLE_READ（可重复读）：</strong></li>
<li><strong>SERIALIZABLE（串行化）：</strong></li>
</ol>
<p>通过<code v-pre>@Transational</code>注解的isolation属性来执行事务隔离级别。</p>
<h2 id="说说spring的事务传播行为" tabindex="-1"><a class="header-anchor" href="#说说spring的事务传播行为"><span>说说Spring的事务传播行为</span></a></h2>
<p>事务的传播特性指的是当一个事务方法被另一个事务方法调用时，这个事务方法应该如何进行？</p>
<ol>
<li><strong>REQUIRED（默认）：</strong> 如果当前存在事务，则加入该事务，如果当前没有事务，则创建一个新的事务。</li>
<li><strong>REQUIRES_NEW:</strong> 无论当前是否存在事务，都创建一个新的事务。如果当前存在事务，则将当前事务挂起。适用于需要独立事务执行场景，不受外部事务的影响。</li>
<li><strong>SUPPORTS：</strong> 如果当前存在事务，则加入该事务。如果当前没有事务，则以非事务方式执行。适用于不需要强制事务的场景，可以与其他事务方法共享事务。</li>
<li><strong>NOT_SUPPORTED:</strong> 以非事务方式执行，如果当前存在事务，则将当前事务挂起。适用于不需要事务支持的场景，可以在方法执行期间暂时禁用事务。</li>
<li><strong>MANDATORY：</strong> 如果当前存在实物，则加入该事务，如果当前没有事务，则抛出异常。适用于必须在事务中执行的场景，如果没有事务则会抛异常。</li>
<li><strong>NESTED：</strong> 如果当前存在事务，则在嵌套事务中执行，如果当前没有事务，则创建一个新的事务。嵌套事务是外部事务的一部分，可以独立提交或回滚。适用于需要再嵌套事务中执行的场景。</li>
<li><strong>NEVER：</strong> 以非事务的方式执行，如果当前存在事务，则抛出异常。适用于不允许在事务中执行的场景，如果存在事务，则会抛出异常。</li>
</ol>
<p>通过<code v-pre>@Transation</code>注解的propagation属性来指定事务传播行为。</p>
<h2 id="spring-aop-和-aspectj-aop有什么区别" tabindex="-1"><a class="header-anchor" href="#spring-aop-和-aspectj-aop有什么区别"><span>Spring AOP 和 AspectJ AOP有什么区别</span></a></h2>
<p><strong>Spring AOP主要用到了AspectJ的@PointCut切点解析能力和切点匹配能力。</strong>
<strong>@Aspect、@Before等这些注解都是由AspectJ发明的。</strong></p>
<p>AspectJ能干很多Spring AOP干不了的事情，它是AOP编程的完全解决方案。Spring AOP致力于解决的事企业级开发中最普遍的AOP需求（方法增强），而不是力求成为一个像AspectJ一样的AOP编程完全解决方案。</p>
<h4 id="区别" tabindex="-1"><a class="header-anchor" href="#区别"><span>区别</span></a></h4>
<ul>
<li><strong>AspectJ</strong>主要通过在编译阶段生成代理类，也称为<strong>编译时增强</strong>。它会在编译阶段将AspectJ（切面）织入到Java字节码中，运行的时候就是增强之后的对象，通过这种方式实现AOP。</li>
<li><strong>Spring AOP</strong>使用的是<strong>动态代理</strong>来增强对象。默认地，如果使用接口的，用JDK提供的动态代理实现，如果没有接口，使用CGLIB实现。Spring AOP在容器启动的时候需要生成代理实例，在方法调用上也会增加栈的深度，使得Spring AOP的性能不如AspectJ那么好。</li>
</ul>
<h2 id="spring-aop通知和执行顺序" tabindex="-1"><a class="header-anchor" href="#spring-aop通知和执行顺序"><span>Spring AOP通知和执行顺序？</span></a></h2>
<p>Spring切面可以应用5种类型的通知：</p>
<ol>
<li><strong>前置通知：</strong> 在目标方法被调用之前调用通知功能；</li>
<li><strong>后置通知：</strong> 在目标方法被调用之后调用通知功能，此时不会关心方法的输出是什么；</li>
<li><strong>返回通知：</strong> 在目标方法成功执行之后调用通知；</li>
<li><strong>异常通知：</strong> 在目标方法抛出异常后调用通知；</li>
<li><strong>环绕通知：</strong> 通知包裹了被通知的方法，在被通知的方法调用之前和调用之后执行自定义的行为。</li>
</ol>
<h4 id="执行顺序" tabindex="-1"><a class="header-anchor" href="#执行顺序"><span>执行顺序：</span></a></h4>
<p>Spring在5.2.7之前的执行顺序时：
正常：前置 -&gt; 方法 -&gt; 后置 -&gt; 返回
异常：前置 -&gt; 方法 -&gt; 后置 -&gt; 异常</p>
<p>Spring在5.2.7之后的执行顺序时：
正常：前置 -&gt; 方法 -&gt; 返回 -&gt; 后置
异常：前置 -&gt; 方法 -&gt; 异常 -&gt; 后置</p>
<h2 id="spring框架中的单例bean是线程安全的吗" tabindex="-1"><a class="header-anchor" href="#spring框架中的单例bean是线程安全的吗"><span>Spring框架中的单例Bean是线程安全的吗</span></a></h2>
<p>在Spring框架中，由于单例Bean在整个Spring上下文只有一个实例，因此在多线程环境下访问该实例时，需要确保Bean的状态是线程安全的。如果单例Bean的状态是可变的，并且多个线程同时修改该状态，<strong>可能会导致线程安全问题</strong>。</p>
<p>为了确保单例Bean的线程安全，可以采取一下几种方式：</p>
<ol>
<li>避免在单例Bean中使用可变的实例变量，或者确保对这些变量的访问是线程安全的，例如使用同步机制（如synchronized关键字）或使用线程安全的数据结构。</li>
<li>尽量避免在单例Bean中使用共享的外部资源，如数据库连接、文件等。如果必须要使用共享资源，需要确保对这些资源的访问是线程安全的（如使用ThreadLocal等）来保证线程安全。</li>
<li>使用无状态的单例Bean。无状态的单例Bean不包含任何实例变量，只包含方法和局部变量，因此不会有线程安全问题。</li>
<li>采用多例Bean。将Bean的作用域改为&quot;property&quot;，即每次使用创建一个新的实例，这样可以有效避免单例Bean共享造成的线程不安全。</li>
</ol>
<h2 id="说说你对spring的理解" tabindex="-1"><a class="header-anchor" href="#说说你对spring的理解"><span>说说你对Spring的理解</span></a></h2>
<p>首先<strong>Spring是一个生态</strong>，可以构建企业级应用程序所需的一切基础设施。
但是，通常Spring指的是Spring Framework，它有两个核心：</p>
<ol>
<li><strong>IOC、DI</strong>的支持
Spring的核心就是一个大的工厂容器，可以维护所有对象的创建和依赖关系，Spring工厂用于生成Bean，并且管理Bean的生命周期，实现<strong>高内聚低耦合</strong>的设计理念。</li>
<li><strong>AOP</strong>编程的支持
Spring提供了<strong>面向切面编程</strong>，面向切面编程允许我们将横切关注点从核心业务逻辑中分离出来，实现代码的模块化和重用。可以方便的实现对程序进行权限拦截、运行监控、日志记录等切面功能。</li>
</ol>
<p>除了这两大核心还提供了丰富的功能和模块，数据访问、事务管理、Web开发等。数据访问模块提供了对数据库的访问支持，可以方便地进行数据库操作。事务管理模块提供了对事务的管理支持，确保数据的一致性和完整性。Web开发模块则提供了构建Web应用程序的工具和框架，简化了Web开发的过程。</p>
<p>总结一句话：<strong>它是一个轻量级、非入侵时的控制反转（IOC）和面向切面（AOP）的容器框架</strong>。</p>
<h2 id="spring有哪些缺点" tabindex="-1"><a class="header-anchor" href="#spring有哪些缺点"><span>Spring有哪些缺点</span></a></h2>
<ol>
<li>学习曲线较陡峭：需要花费一定的时间理解和掌握Spring的核心概念和特性。</li>
<li>配置复杂：Spring框架的配置通常使用XML或注解进行，这种配置方法可能会导致配置文件变得复杂和冗长。这个问题在SpringBoot中得到解决。</li>
<li>运行时性能：由于提供了很多功能和特性，它的运行时性能可能相对较低。</li>
<li>过度依赖：开发人员可能会过度依赖Spring框架，导致项目的可移植性和可维护性下降。</li>
<li>文档和社区支持：有时候可能会遇见文档不完善或社区资源有限的情况。</li>
</ol>
<h2 id="autowired与resource区别" tabindex="-1"><a class="header-anchor" href="#autowired与resource区别"><span>AutoWired与Resource区别</span></a></h2>
<h4 id="autowired" tabindex="-1"><a class="header-anchor" href="#autowired"><span>AutoWired</span></a></h4>
<p>AutoWired是<strong>Sping框架</strong>提供的一个注解，它<strong>默认是根据类型来实现Bean的依赖注入</strong>。</p>
<p>在这个注解中，有一个required属性，默认值是true，表示<strong>必须实例化一个注入的Bean。如果找不到对应类型的Bean，会在应用启动时报错</strong>。</p>
<p>此外，<strong>在Spring IOC容器中存在多个相同类型的Bean实例，AutoWired会按照byType查找，然后再按照byName查找</strong>，如果都找不到就会提示异常。</p>
<p>针对这种情况，我们可以使用primary或者Quanlifier者两个注解来解决。
<strong>primary</strong> 表示优先级，当存在多个相同类型的Bean时，优先使用声明了primary注解的Bean。
<strong>Quanlifier</strong> 类似与条件筛选，根据指定的Bean名称查找目标Bean。</p>
<h4 id="resource" tabindex="-1"><a class="header-anchor" href="#resource"><span>Resource</span></a></h4>
<p>Resource是JDK提供的注解，<strong>Resource默认先按照byName查找Bean，然后再按照byType查找Bean</strong>，同时也支持指定由哪种方式查找Bean。</p>
<h2 id="mybatis的一、二级缓存和spring的一、二级缓存有什么关系。" tabindex="-1"><a class="header-anchor" href="#mybatis的一、二级缓存和spring的一、二级缓存有什么关系。"><span>Mybatis的一、二级缓存和Spring的一、二级缓存有什么关系。</span></a></h2>
<p>Mybatis的一、二级缓存时用来存储查询结果，<strong>一级缓存会在同一个SqlSession</strong>的重复查询结果进行缓存，<strong>二级缓存则是全局应用下</strong>的重复查询结果进行缓存。</p>
<p>Spring的一、二级缓存时用来存储Bean的，<strong>一级缓存用来存储完整最终使用的Bean，二级缓存用来存储早期的临时Bean。当然还有一个三级缓存用来解决循环依赖的</strong>。</p>
<h2 id="resttemplate连接池如何优化" tabindex="-1"><a class="header-anchor" href="#resttemplate连接池如何优化"><span>RestTemplate连接池如何优化</span></a></h2>
<h2 id="说说你对spring事务和aop底层实现原理的区别" tabindex="-1"><a class="header-anchor" href="#说说你对spring事务和aop底层实现原理的区别"><span>说说你对Spring事务和AOP底层实现原理的区别</span></a></h2>
<p>Spring的声明式事务其实也是通过AOP的底层原理实现的，都是通过同一个Bean的后置处理器来完成的动态代理创建，只不过：</p>
<ol>
<li>创建动态代理的匹配方式不同：
AOP的增强通知是通过切面+切点+通知来完成的，在创建Bean时发现Bean和切点表达式匹配就会创建动态代理。
而事务内置一个增强类，在创建Bean的时候，一旦发现你的类加了@Transactional注解就会创建动态代理。</li>
<li>执行动态代理的增强不同：
在执行AOP的Bean时，会先执行动态代理的增强类，通过责任链分别按顺序执行通知。
在执行事务的bean时，会先执行动态代理的增强类，在执行目标方法前进行异常捕捉，出现异常回滚事务，无异常提交事务。</li>
</ol>
<h2 id="springmvc的拦截器和过滤器有什么区别-执行顺序" tabindex="-1"><a class="header-anchor" href="#springmvc的拦截器和过滤器有什么区别-执行顺序"><span>SpringMVC的拦截器和过滤器有什么区别？执行顺序？</span></a></h2>
<ol>
<li><strong>归属不同：</strong> <strong>拦截器是SpringMVC框架的一部分，而过滤器是Servlet规范的一部分</strong>。拦截器主要用于对<strong>控制器层</strong>的请求进行处理，它们提供了更细粒度的控制，可以在请求进入控制器之前和之后执行特性的逻辑，例如身份验证、日志记录和权限检查。过滤器独立于Spring MVC，用于<strong>处理通用的请求和响应内容</strong>，例如字符编码、压缩和安全性。</li>
<li><strong>执行顺序不同：</strong> 拦截器的执行顺序有配置文件中的顺序决定，可以有多个拦截器，它们按照配置的顺序依次执行。而过滤器的执行顺序由web.xml文件中的配置顺序决定，同样可以有多个过滤器，按照配置的顺序执行。一般来说，首先执行过滤器，然后再执行拦截器。</li>
<li><strong>用途不同：</strong> 拦截器用于对SpringMVC的请求和响应进行特定的业务处理，通常与控制层请求处理有关。过滤器用于对所有Servlet请求和响应进行通用性处理。通常关注请求和响应的内容，而不涉及具体的业务逻辑。</li>
</ol>
<h2 id="spring和springmvc为什么需要父子容器" tabindex="-1"><a class="header-anchor" href="#spring和springmvc为什么需要父子容器"><span>Spring和SpringMVC为什么需要父子容器？</span></a></h2>
<p>可以帮助划分功能边界，使得大型应用更易于管理。通过讲不同模块或层次的组件分别放置在父子容器，能够清晰地定义每个容器的职责，从而提高了代码的可维护性和可扩展性。</p>
<h2 id="spring框架中都用到了那些设计模式" tabindex="-1"><a class="header-anchor" href="#spring框架中都用到了那些设计模式"><span>Spring框架中都用到了那些设计模式？</span></a></h2>
<ol>
<li><strong>简单工厂：</strong></li>
<li><strong>工厂方法：</strong></li>
<li><strong>单例模式：</strong></li>
<li><strong>适配器模式：</strong></li>
<li><strong>装饰器模式：</strong></li>
<li><strong>代理模式：</strong></li>
<li><strong>观察者模式：</strong></li>
<li><strong>策略模式：</strong></li>
<li><strong>模板方法模式：</strong></li>
<li><strong>责任链模式：</strong></li>
</ol>
<h2 id="spring事件监听的核心机制是什么" tabindex="-1"><a class="header-anchor" href="#spring事件监听的核心机制是什么"><span>Spring事件监听的核心机制是什么？</span></a></h2>
<p><strong>观察者模式：</strong> 它允许一个对象（称为主题或被观察者）维护一组依赖于它的对象（称为观察者），并在主题状态发生变化时通知观察者。</p>
<ol>
<li><strong>事件：</strong> 事件是观察者模式中的主题状态变化的具体表示，它封装了事件发生时的信息。在Spring中，事件通常是普通的Java对象，用于传递数据或上下文信息。</li>
<li><strong>事件发布者：</strong> 在Spring中，事件发布者充当主题的角色，负责出发并发布事件。它通常实现了<strong>ApplicationEventPublisher</strong>接口或使用注解**@AutoWired**来获得事件发布功能。</li>
<li><strong>事件监听器：</strong> 事件监听器充当观察者的角色，负责监听并响应时间的发生。它实现了<strong>ApplicationListener</strong>接口，通过**onApplicationEvent()**方法来处理时间。</li>
</ol>
<p>总之，Spring事件监听机制的核心机制是观察者模式，通过事件、事件发布者和事件监听器的协作，实现了松耦合的组件通信，使得应用程序更加灵活和可维护。</p>
<h2 id="spring事务的失效原因" tabindex="-1"><a class="header-anchor" href="#spring事务的失效原因"><span>Spring事务的失效原因？</span></a></h2>
<p>大部分失效是由于：</p>
<ol>
<li><strong>方法时private也会失效，解决：改成public：</strong></li>
<li><strong>目标类没有配置为Bean也会失效，解决：配置为Bean：</strong></li>
<li><strong>自己捕获了异常，解决：不要捕获异常：</strong></li>
<li><strong>使用CGLIB动态代理，但@Transactional声明在接口上：</strong></li>
<li><strong>跨越多个线程的事务管理，解决：使用编程式事务或分布式事务：</strong></li>
<li><strong>事物传播属性或捕获异常等属性设置不正确：</strong></li>
</ol>
<h2 id="spring多线程事务-能否保证事务的一致性" tabindex="-1"><a class="header-anchor" href="#spring多线程事务-能否保证事务的一致性"><span>Spring多线程事务，能否保证事务的一致性？</span></a></h2>
<p>在多线程环境下，Spring事务管理默认情况下无法保证全局事务的一致性。这是因为Spring的本地事务管理是基于线程的，每个线程都有自己的独立事务。</p>
<ol>
<li>Spring的事务管理通常将事务信息存储在ThreadLocal中，这意味着每个线程只能拥有一个事务。这确保了在单个线程内的数据库操作处于同一个事务中，保证了原子性。</li>
<li><strong>可以通过如下方案进行解决：</strong>
<ul>
<li><strong>编程式事务：</strong></li>
<li><strong>分布式事务：</strong></li>
</ul>
</li>
</ol>
<h2 id="什么情况下aop会失效-怎么解决" tabindex="-1"><a class="header-anchor" href="#什么情况下aop会失效-怎么解决"><span>什么情况下AOP会失效？怎么解决？</span></a></h2>
<ol>
<li><strong>内部方法调用：</strong></li>
<li><strong>静态方法：</strong></li>
<li><strong>AOP配置问题：</strong></li>
<li><strong>代理问题：</strong></li>
</ol>
<h2 id="jdk动态代理和cglib动态代理的区别" tabindex="-1"><a class="header-anchor" href="#jdk动态代理和cglib动态代理的区别"><span>JDK动态代理和CGLIB动态代理的区别？</span></a></h2>
<ol>
<li><strong>从性能上特性对比：</strong></li>
<li><strong>从创建代理时的性能对比：</strong></li>
<li><strong>从调用时的性能对比：</strong></li>
</ol>
<h2 id="说说springaop的底层实现" tabindex="-1"><a class="header-anchor" href="#说说springaop的底层实现"><span>说说SpringAOP的底层实现</span></a></h2>
<p>底层实现主要分为两部分：<strong>创建动态代理</strong>和<strong>调用代理</strong>。</p>
<p><strong>在启动Spring时会创建AOP动态代理：</strong></p>
<p><strong>在调用阶段：</strong></p>
<h2 id="spring是如何解决bean的循环依赖" tabindex="-1"><a class="header-anchor" href="#spring是如何解决bean的循环依赖"><span>Spring是如何解决Bean的循环依赖？</span></a></h2>
<p><strong>三级缓存</strong>解决循环依赖。</p>
<p><strong>一级缓存singletonObjects存放的是可以使用的单例Bean。</strong>
<strong>二级缓存earlySingletonObjects存放的是早期的Bean，即半成品，此时还无法使用。</strong>
<strong>三级缓存singletonFactories是一个对象工厂，用于创建对象并放入二级缓存中</strong>。同时，如果对象有AOP代理，则对象工厂返回代理对象。</p>
<ol>
<li>二级缓存能不能解决循环依赖？
<ul>
<li>如果只是循环依赖导致的死循环问题：一级缓存就可以解决，但是解决在并发下获取不完整的Bean。</li>
<li>二级缓存完全解决循环依赖：只是需要在实例化后就创建动态代理，不优化也不符合Spring生命周期规范。</li>
</ul>
</li>
<li>Spring有没有解决多例Bean的循环依赖？
<ul>
<li>多例不会使用缓存进行存储（多例Bean每次使用都需要重新创建）。</li>
<li>不缓存早期对象就无法解决循环。</li>
</ul>
</li>
<li>Spring有没有构造函数参数Bean的循环依赖？
<ul>
<li>构造函数的循环依赖也是会报错。</li>
<li>可以通过人工进行解决：@Lazy，就不会立即创建依赖的Bean了，而是等到用到才通过动态代理进行创建。</li>
</ul>
</li>
</ol>
<h2 id="解释spring中bean的生命周期" tabindex="-1"><a class="header-anchor" href="#解释spring中bean的生命周期"><span>解释Spring中Bean的生命周期</span></a></h2>
<p>Bean的生命周期：指的是Bean从创建到销毁的整个过程：分4大步：</p>
<ol>
<li><strong>实例化：</strong>
<ul>
<li>通过反射去推断构造函数进行实例化（实例工厂、静态工厂）。</li>
</ul>
</li>
<li><strong>依赖注入（DI）</strong>
<ul>
<li>解析自动装配（byName、byType）</li>
</ul>
</li>
<li><strong>初始化</strong>
<ul>
<li>调用很多Aware回调方法</li>
<li>调用BeanPostProcessor.postProcessBeforeInitialization</li>
<li>调用生命周期回调初始化方法</li>
<li>调用BeanPostProcessor.postProcessBeforeInitialization，如果Bean实现AOP则会在这里创建动态代理</li>
</ul>
</li>
<li><strong>销毁</strong>
<ul>
<li>在Spring容器关闭的时候进行调用销毁方法</li>
</ul>
</li>
</ol>
<h2 id="spring-ioc的实现机制是什么" tabindex="-1"><a class="header-anchor" href="#spring-ioc的实现机制是什么"><span>Spring IOC的实现机制是什么？</span></a></h2>
<p>Spring的IOC底层实现机制主要以来一下几个关键组件和技术：</p>
<ol>
<li><strong>反射：</strong></li>
<li><strong>配置元数据：</strong></li>
<li><strong>Bean定义：</strong></li>
<li><strong>Bean工厂：</strong></li>
<li><strong>依赖注入：</strong></li>
</ol>
<h2 id="bean有哪些配置方式" tabindex="-1"><a class="header-anchor" href="#bean有哪些配置方式"><span>Bean有哪些配置方式？</span></a></h2>
<ol>
<li><strong>XML配置：</strong></li>
<li><strong>注解配置：</strong></li>
<li><strong>JavaConfig方式：</strong></li>
<li><strong>@Import：</strong></li>
<li><strong>Groovy配置：</strong></li>
<li><strong>JSR-330：</strong></li>
</ol>
<h2 id="beanfactory和applicationcontext有什么区别" tabindex="-1"><a class="header-anchor" href="#beanfactory和applicationcontext有什么区别"><span>BeanFactory和ApplicationContext有什么区别？</span></a></h2>
<p>BeanFactory和ApplicationContext是Spring的两大核心接口，都可以当作Spring容器。其中ApplicationContext是BeanFactory的字节偶。</p>
<p>BeanFactory：是Spring框架的核心接口之一，可称之为<strong>低级容器</strong>。Bean的生产过程分为【配置的解析】和【Bean的创建】，而BeanFactory只有Bean的创建功能，说明它内存占用更小。</p>
<p>ApplicationContext，可称之为<strong>高级容器</strong>。它继承了很多接口，代表着整个大容器的所有功能。</p>
<h2 id="beanfactory和factorybean有什么区别" tabindex="-1"><a class="header-anchor" href="#beanfactory和factorybean有什么区别"><span>BeanFactory和FactoryBean有什么区别？</span></a></h2>
<p><code v-pre>BeanFactory</code>是Spring框架的核心接口之一，用于管理和获取Bean对象，是一个Bean容器。使用简单工厂模式，提供getBean用来获取Bena。</p>
<p><code v-pre>FactoryBean</code>是一个Bean，但它是一个特殊的bean,它是一个接口，它必须被一个Bean去实现。
Factorybean接口定义了两个方法：<code v-pre>getObject()</code>和<code v-pre>getObjectType()</code>。
getObject()：用于返回创建的Bean对象，最终该Bean对象会进行注入。（Mybatis集成Spring时的那个SqlSessionFactoryBean就实现了FactoryBean，最终通过getObject()将SqlSessionFactory注入到IOC容器中。）
getObjectType()：用于返回创建的Bean对象的类型。</p>
<h2 id="spring-ioc容器的加载过程" tabindex="-1"><a class="header-anchor" href="#spring-ioc容器的加载过程"><span>Spring IOC容器的加载过程</span></a></h2>
<p>分为两个阶段：：<strong>配置解析阶段</strong>和<strong>Bean的创建阶段</strong>。</p>
<h4 id="配置解析阶段" tabindex="-1"><a class="header-anchor" href="#配置解析阶段"><span>配置解析阶段</span></a></h4>
<p>配置解析阶段主要做的工作是加载和解析配置文件，将配置的Bean解析成BeanDefinition，整个过程是：</p>
<ul>
<li>读取配置：通过BeanDefinitionReader读取配置文件或配置类。</li>
<li>解析配置信息：如ComponentScan、Bean配置等。</li>
<li>扫描类注解：根据ComponentScan扫描@Component、@Bean、@Configuration、@Import等注解。</li>
<li>将符合的Bean注册为BeanDefinition</li>
</ul>
<h4 id="bean的创建阶段" tabindex="-1"><a class="header-anchor" href="#bean的创建阶段"><span>Bean的创建阶段</span></a></h4>
<p>Bean的阶段主要做的工作是根据BeanDefinition创建Bean。大概过程是：</p>
<ul>
<li>实例化Bean：容器根据配置文件中的Bean定义，实例化Bena对象。可以通过构造函数实例化、工厂方法实例化、静态工厂实例化来创建Bean对象。</li>
<li>注入Bean属性：容器会为实例化的Bean对象设置属性值，可以通过setter注入属性值，也可以通过构造函数注入属性值。</li>
<li>处理依赖关系：容器会处理Bean之间的依赖关系，将依赖的Bean注入到需要的地方。</li>
<li>执行初始化方法：容器会调用Bean的初始化方法，可以通过实现InitializingBean忌口或者在配置文件中执行初始化方法来定义Bean的初始化逻辑。</li>
<li>注册Bean：容器会将实例化、属性设置和初始化完成的Bean对象注册到容器中，以便后续的使用和管理。</li>
<li>完成加载：容器完成所有Bean的加载和初始化后，即完成了IOC容器的加载过程。此时，可以通过容器调用getBean方法获取Bean对象。</li>
</ul>
<h2 id="" tabindex="-1"><a class="header-anchor" href="#"><span></span></a></h2>
<h2 id="-1" tabindex="-1"><a class="header-anchor" href="#-1"><span></span></a></h2>
<h2 id="-2" tabindex="-1"><a class="header-anchor" href="#-2"><span></span></a></h2>
<h2 id="-3" tabindex="-1"><a class="header-anchor" href="#-3"><span></span></a></h2>
<h2 id="-4" tabindex="-1"><a class="header-anchor" href="#-4"><span></span></a></h2>
<h2 id="-5" tabindex="-1"><a class="header-anchor" href="#-5"><span></span></a></h2>
<h2 id="-6" tabindex="-1"><a class="header-anchor" href="#-6"><span></span></a></h2>
<h2 id="-7" tabindex="-1"><a class="header-anchor" href="#-7"><span></span></a></h2>
<h2 id="-8" tabindex="-1"><a class="header-anchor" href="#-8"><span></span></a></h2>
<h2 id="-9" tabindex="-1"><a class="header-anchor" href="#-9"><span></span></a></h2>
<h2 id="-10" tabindex="-1"><a class="header-anchor" href="#-10"><span></span></a></h2>
<h2 id="-11" tabindex="-1"><a class="header-anchor" href="#-11"><span></span></a></h2>
<h2 id="-12" tabindex="-1"><a class="header-anchor" href="#-12"><span></span></a></h2>
<h2 id="-13" tabindex="-1"><a class="header-anchor" href="#-13"><span></span></a></h2>
<h2 id="-14" tabindex="-1"><a class="header-anchor" href="#-14"><span></span></a></h2>
<h2 id="-15" tabindex="-1"><a class="header-anchor" href="#-15"><span></span></a></h2>
<h2 id="-16" tabindex="-1"><a class="header-anchor" href="#-16"><span></span></a></h2>
<h2 id="-17" tabindex="-1"><a class="header-anchor" href="#-17"><span></span></a></h2>
<h2 id="-18" tabindex="-1"><a class="header-anchor" href="#-18"><span></span></a></h2>
<h2 id="-19" tabindex="-1"><a class="header-anchor" href="#-19"><span></span></a></h2>
<h2 id="-20" tabindex="-1"><a class="header-anchor" href="#-20"><span></span></a></h2>
</div></template>


